(function () {
  // requestAnimationFrame兼容性处理
  var lastTime = 0;
  var vendors = ['webkit', 'moz'];
  for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
  }
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = function (callback, element) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = window.setTimeout(function () {
          callback(currTime + timeToCall);
        },
        timeToCall);
      lastTime = currTime + timeToCall;
      return id;
    };
  }
  if (!window.cancelAnimationFrame) {
    window.cancelAnimationFrame = function (id) {
      clearTimeout(id);
    };
  }
  //缓动算法·策略类
  var tween = {
    linear: function (t, b, c, d) {
      return c * t / d + b;
    },
    easeIn: function (t, b, c, d) {
      return c * (t /= d) * t + b;
    },
    strongEaseIn: function (t, b, c, d) {
      return c * (t /= d) * t * t * t * t + b;
    },
    strongEaseOut: function (t, b, c, d) {
      return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
    },
    sineaseIn: function (t, b, c, d) {
      return c * (t /= d) * t * t + b;
    },
    sineaseOut: function (t, b, c, d) {
      return c * ((t = t / d - 1) * t * t + 1) + b;
    }
  };
  // Roll滚动类
  function Roll(ball, target, duration, easing) {
    this.dom = null;
    this.ball = ball;
    this.target = target;
    this.easing = tween[easing] || tween.linear;
    this.duration = duration || 500;
    this.startTime = 0;
    this.status = false;
    this.setPos('end', target);
  }
  // 移动
  Roll.prototype.move = function (dom) {
    if (this.status) return;
    this.dom = dom;
    this.status = true;
    this.setPos('start', dom);
    this.update(this.startX, this.startY);
    this.startTime = +new Date;
    var self = this;
    var timer = requestAnimationFrame(function request() {
      if (self.step() == false) {
        cancelAnimationFrame(timer);
      } else {
        requestAnimationFrame(request);
      }
    });
  }
  // 设置开始和结束位置
  Roll.prototype.setPos = function (type, dom) {
    var rect = dom.getBoundingClientRect();
    var x = rect.left;
    var y = rect.top;
    if (type == 'end') {
      x += rect.width / 2;
      y += rect.height / 2;
    }
    this[type + 'X'] = x;
    this[type + 'Y'] = y;
  }
  // 步长
  Roll.prototype.step = function () {
    var curTime = +new Date;
    var startTime = this.startTime;
    var duration = this.duration;
    var time = curTime - startTime;
    if (curTime >= startTime + duration) time = duration;
    var startX = this.startX;
    var startY = this.startY;
    var endX = this.endX;
    var endY = this.endY;
    var posX = this.easing(time, startX, endX - startX, duration);
    var posY = this.easing(time, startY, endY - startY, duration);
    this.update(posX, posY);
    if (time == duration) {
      this.ball.style.display = 'none';
      return this.status = false;
    };
  };
  // 更新位置
  Roll.prototype.update = function (x, y) {
    var pos = ['', '-webkit-', '-moz-'].map(function (prefix, i, arr) {
      return prefix + 'transform:translate(' + x + 'px,' + y + 'px) translateZ(0px);';
    })
    this.ball.style.cssText = pos.join("") + 'display: block';
  };
  // 注册Roll
  window.Roll = Roll;
})();